package com.tang.common.config.shiroConfig;

import cn.hutool.core.bean.BeanUtil;
import com.tang.common.entity.UserEntity;
import com.tang.common.feign.UserCenterFeign;
import com.tang.common.utils.JwtUtils;
import com.tang.common.vo.R;
import io.jsonwebtoken.Claims;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;

import javax.annotation.Resource;
import java.lang.reflect.Method;

@Slf4j
public class UserRealm extends AuthorizingRealm {
    @Autowired
    private ApplicationContext context;
    @Autowired
    @Lazy
    private UserCenterFeign userCenterFeign;
    @Value("${spring.application.name}")
    private String appName;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 认证
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getPrincipal();

        if ("user-center".equals(appName)){
            Claims claims = JwtUtils.decodeToken(token);
            Object userService = context.getBean("userServiceImpl");
            Class<?> aClass = userService.getClass();
            Method getUserByUserName = aClass.getMethod("getUserByUserName", String.class);
            Object obj = getUserByUserName.invoke(userService,claims.get("userName").toString());
            UserEntity entity = BeanUtil.copyProperties(obj, UserEntity.class);
            // 账户不存在，抛出异常 unknownAccountException
            if (entity == null)return null;
            if (!JwtUtils.verify(token,entity))throw new IncorrectCredentialsException();
        }else {
            R auth = userCenterFeign.auth(token);
            if (!auth.isSuccess())throw new IncorrectCredentialsException();
        }

        // 密码认证（加盐）
        return new SimpleAuthenticationInfo(token,token,getName());
    }
}
